/**
 * class name: icalendar,
 * copyright: maximus zhang,
 * License: MIT-LICENSE,
 * contact: maximus.zhang@gmail.com,
 * required-js: http://jsease.googlecode.com/svn/trunk/core.js, mask.js, ipop.js,
 * update: http://jsease.googlecode.com/svn/trunk/icalendar.js
 *
 */
function icalendar(){/* {id, } */
    var A = arguments,
        _ = this;
    _ = ext( _, ext({
        id : 'icalnd'+ now(3),
        width:175,
        height:160,
        elem: me.body,
        target:'',
        weekday: ['&#26085;','&#19968;','&#20108;','&#19977;','&#22235;','&#20116;','&#20845;'],
        format: 'yyyy-mm-dd'
        }, A[0] ) );

    _.uitype = 'icalendar';

    _.elem = $(_.elem) || me.body;
    _.showed = _.focused = false;

    _.now = now();
    _.today = {yy: _.now.getFullYear(), mm: _.now.getMonth()+1, dd: _.now.getDate()};
    _.curday = {};
    _.defyy = 0;
    _.defmm = 0;
    _.defdd = 0;
}
icalendar.prototype = {
    getDefaultDay : function (ds, f) {
        var _ = this;
        if ( !ds || (ds.indexOf('/')==-1&&ds.indexOf('-')==-1) ) {
            if (_.elem.nodeName =='INPUT'){
                _.elem.value='';
            } else {
                _.elem.empty();
            }
            return {};
        }

        var f = f || _.format;

        switch ( f ) {
            case 'yyyy/mm/dd':
            case 'yyyy/m/d':
                var ad = ds.split('/');
                _.defyy = ad[0].toInt();
                _.defmm = ad[1].toInt();
                _.defdd = ad[2].toInt();
            break;
            default:
                var ad = ds.split('-');
                _.defyy = ad[0].toInt();
                _.defmm = ad[1].toInt();
                _.defdd = ad[2].toInt();
            break;
       }
    return {yy: _.defyy, mm: _.defmm, dd: _.defdd};
    },

    formatDate : function (od, f) {/* od like {yy:year, mm:month, dd:day} */
        var _ = this;
        var s = '',
            f = f || _.format;
        switch ( f ) {
            case 'yyyy-mm-dd':
                s = od.yy +'-'+ (od.mm<10 ? '0':'') + od.mm +'-'+ (od.dd<10 ? '0':'') + od.dd;
            break;
            default:
                s = od.yy +'-'+ od.mm +'-'+  od.dd;
            break;
        }
    return s;
    },

    hide : function(seled){
        var _ = this;
        if ( 1==seled ) {
            _.showed = _.focused = false;
            _.ipop.hide();
            unbind(me, 'mousedown', function(){_.hide();});
            _.bound = 0;
        }
        if ( !_.showed && _.focused ) {
            return _;
        }
        if ( !_.showed && !_.focused ) {
            _.ipop.hide();
            unbind(me, 'mousedown', function(){_.hide();});
            _.bound = 0;
        }

    return _;
    },

    show : function(msg){
        var _ = this;
        if ( 1==_.bound ) {
            return _;
        }
        _.poz = pos(_.elem);

        var ds = _.elem.nodeName=='INPUT' ? _.elem.value : _.elem.innerHTML;

        if ( ds.length ) {
            _.curday = _.getDefaultDay(ds);
            _.setYs().setMs().setDs();
        }

        _.ipop.show({css:'position:absolute;top:'+ _.poz._bottom +'px;left:'+ (_.poz.left+1) +'px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;z-index:10001;', data:_.$});

        bind(me, 'mousedown', function(){_.hide();});

        _.bound = 1;
        _.showed = true;
    return _;
    },

    reset : function () {
        this.curday = {};
        this.defdd = 0;
        this.defyy = 0;
        this.defmm = 0;
        this.setYs().setMs().setDs();
    return this;
    },

    setYs : function () {
        var _ = this;
        if ( hop(_.curday, 'yy') ) {
            setSelect(_.ys, _.curday.yy);
        } else {
            setSelect(_.ys, _.today.yy);
            _.curday.yy = _.today.yy;
        }
    return _;
    },

    setMs : function () {
        var _ = this;
        if ( hop(_.curday, 'mm') ) {
            setSelect(_.ms, _.curday.mm);
        } else {
            setSelect(_.ms, _.today.mm);
            _.curday.mm = _.today.mm;
        }
    return _;
    },

    setMs2 : function (n) {
        var _ = this;
        var n = 1==n ? 1 : -1;
        switch ( n ) {
            case -1:
                if ( _.curday.mm==1 ) {
                    _.curday.yy-=1;
                    _.curday.mm = 12;
                } else {
                    _.curday.mm-=1;
                }
            break;
            case 1:
                if ( _.curday.mm==12 ) {
                    _.curday.yy+=1;
                    _.curday.mm = 1;
                } else {
                    _.curday.mm+=1;
                }
            break;
        }
    return _.setYs().setMs().setDs();
    },

    selDay : function () {
        var _ = this;
        if ( _.elem.nodeName=='INPUT' ) {
            _.elem.value = _.formatDate( _.curday, _.format );
        } else {
            _.elem.innerHTML = _.formatDate( _.curday, _.format );
        }
    return _.hide(1);
    },

    setDs : function () {
        var _ = this;
        _.days.empty();
        _.enday = 32 - new Date(_.curday.yy, _.curday.mm-1, 32).getDate();

        var delta0 = 1, delta1 = 7;

        _.m0wd = new Date(_.curday.yy, _.curday.mm-1, 1).getDay();
        if ( _.m0wd ===0 ) {
            delta0 = -6;
        }
        _.m1wd = new Date(_.curday.yy, _.curday.mm-1, _.enday).getDay();
        if ( _.m1wd == 6 ) {
            delta1 = 14;
        }

        _.pvday = 32 - new Date(_.curday.yy, _.curday.mm-2, 32).getDate();
        for ( var k=_.pvday-_.m0wd+delta0, L=_.pvday; k<=L; k++ ) {
            var dd = elm('dd').setClass('day').appendTo(_.days);
            var da = elm('a').setClass('pnd pnm').attr('href', '#')
                    .attr('day', k).html(k).appendTo(dd);
            da.onclick=function () {
                _.curday.dd = attr(this, 'day').toInt();
                _.setMs2().selDay();
            return false;
            };
        }

        for ( var d=1, L=_.enday; d<=L; d++) {
            var dd = elm('dd').setClass('day').appendTo(_.days);
            var da = elm('a').setClass( (_.curday.yy==_.today.yy
                    && _.curday.mm==_.today.mm
                    && d==_.today.dd ? 'act' : 'pnd')
                    + (_.curday.yy==_.defyy
                    && _.curday.mm==_.defmm
                    && d==_.defdd ? ' sel' : '') )
                    .attr('href', '#').attr('day', d).html(d).appendTo(dd);
            da.onclick=function () {
                _.curday.dd = attr(this, 'day').toInt();
                _.selDay();
            return false;
            };
        }

        for ( var k=1, L=delta1-_.m1wd; k<L; k++ ) {
            var dd = elm('dd').setClass('day').appendTo(_.days);
            var da = elm('a').setClass('pnd pnm').attr('href', '#')
                    .attr('day', k).html(k).appendTo(dd);
            da.onclick=function () {
                _.curday.dd = attr(this, 'day').toInt();
                _.setMs2(1).selDay();
            return false;
            };
        }
    return _;
    },

    init : function(){
        var _ = this;
        _.$ = elm('div').appendTo(me.body).setClass('ical');
        _.id = _.$.id = p(_, 'id') && !$(_.id) ? _.id : ('icalnd_'+ now(3));

        /* ipop.js required */
        _.ipop = (new ipop( { id: _.id +'_ipop', nomask: 1, notitle: 1, autocenter:0, z:10001, data: _.$ } )).init();

        _.elem.onfocus = _.elem.onclick = function () {
            _.show();
        };

        _.elem.onblur = function () {
            _.showed = false;
        return _.hide();
        };

        _.ipop.$.onmouseover = function () {
            _.focused = true;
        return true;
        };
        _.ipop.$.onmouseout = function () {
            _.focused = false;
        return true;
        };

        _.getDefaultDay(_.elem.nodeName=='INPUT' ? _.elem.value : _.elem.innerHTML);

        /* year month control */
        _.ym = elm('div').setClass('yymm').appendTo(_.$);
        _.ms0 = elm('div').setClass('mosel').appendTo(_.ym);
        _.ms0a = elm('a').setClass('mms').attr('href', '#').html('&lt;&lt;')
            .appendTo(_.ms0);
        _.ms0a.onclick=function () {
            _.setMs2();
        return false;
        };

        _.ys = elm('select').setClass('ysel').appendTo(_.ym);
        for ( var y=_.today.yy+5, L=_.today.yy-100; y>L; y--) {
            elm('option').attr('value', y).appendTo(_.ys).html(y);
        }
        _.ys.onchange = function () {
            _.curday.yy = this.value.toInt();
            _.setDs();
        return true;
        };
        _.ytxt = elm('div').setClass('ymtxt').html('&#24180;').appendTo(_.ym);

        _.ms = elm('select').setClass('msel').appendTo(_.ym);
        for ( var m=1; m<13; m++ ) {
            elm('option').attr('value', m).appendTo(_.ms).html(m);
        }
        _.ms.onchange = function () {
            _.curday.mm = this.value.toInt();
            _.setDs();
        return true;
        };
        _.mtxt = elm('div').setClass('ymtxt').html('&#26376;').appendTo(_.ym);

        _.ms1 = elm('div').setClass('mosel').appendTo(_.ym);
        _.ms1a = elm('a').setClass('mms').attr('href', '#').html('&gt;&gt;')
            .appendTo(_.ms1);
        _.ms1a.onclick=function () {
            _.setMs2(1);
        return false;
        };

        /* weekday label */
        _.wkd = elm('dl').setClass('wkd').appendTo(_.$);
        for ( var k=0, L=_.weekday.length; k<L; k++ ) {
            elm('dd').setClass('wd').appendTo(_.wkd).html(_.weekday[k]);
        }
        /* days of month */
        _.days = elm('dl').setClass('days').appendTo(_.$);

        _.setYs().setMs().setDs();

    return _;
    }

};